import tkinter as tk
from tkinter import messagebox

# 获取数据
def val(data_str):
    # 将输入的字符串按空格分割成列表
    arr = data_str.split()
    num = []
    for item in arr:
        try:
            # 将每个元素转换为整数
            num.append(int(item))
        except ValueError:
            messagebox.showerror("输入错误", "请输入有效的整数数据，用空格分隔。")
            return []
    return num

# 层次聚类
def layers(d):
    len_d = len(d)
    if len_d < 2:
        return
    # 以身高的平均数作为分类标准
    sum_d = sum(d)
    # 计算平均数
    mid = sum_d / len_d
    small = []  # 小组
    big = []  # 大组
    for val in d:
        if val <= mid:
            small.append(val)
        else:
            big.append(val)
    print("层次聚类：")
    # 显示分类过程
    print(small)
    print(big)
    # 递归
    layers(small)
    layers(big)

# 距离聚类
def distances(d):
    len_d = len(d)
    # 距离总值的数组
    ls = []
    for i in range(len_d):
        a = d[i]
        sum_dist = 0
        for j in range(len_d):
            b = d[j]
            sum_dist += abs(a - b)
        ls.append(sum_dist)
    # 寻找距离总中数值最小的作为分类中心，默认第一个
    key = 0
    min_val = ls[key]
    for k in range(len(ls)):
        if ls[k] < min_val:
            min_val = ls[k]
            key = k
    # 显示距离分类中心
    print('距离聚类中心：', d[key])

# 密度聚类
def densities(d, step=10):
    # 设置范围
    ls = []
    for i in range(len(d)):
        # 统计区域内的数量
        min_val = d[i] - step
        max_val = d[i] + step
        count = 0
        for j in range(len(d)):
            # 必须在区间内
            if min_val <= d[j] <= max_val:
                count += 1
        ls.append(count)
    # 寻找密度最大的作为分类中心，默认第一个
    key = 0
    num = ls[key]
    for k in range(len(ls)):
        if ls[k] > num:
            num = ls[k]
            key = k
    # 显示密度分类中心
    print('密度聚类中心：', ls, d[key])

# 开始聚类
def start():
    data_str = entry.get()
    data = val(data_str)
    if data:
        layers(data)
        distances(data)
        densities(data, 5)

# 创建主窗口
root = tk.Tk()
root.title("聚类算法")

# 创建标签
label = tk.Label(root, text="身高数据")
label.pack()

# 创建输入框
entry = tk.Entry(root)
entry.insert(0, "160 170 165 180 163 175")
entry.pack()

# 创建按钮
button = tk.Button(root, text="开始聚类", command=start)
button.pack()

# 运行主循环
root.mainloop()